package icu.zhhll.lp.strategy;

import icu.zhhll.lp.LpSolver;
import org.ojalgo.optimisation.ExpressionsBasedModel;
import org.ojalgo.optimisation.Optimisation;
import org.ojalgo.optimisation.solver.ortools.SolverORTools;
import org.ojalgo.type.context.NumberContext;

import java.math.BigDecimal;

/**
 * OjAlgo 策略
 *
 * @author zh
 * @date 2022/12/16 17:00
 */
public class OjAlgoStrategy implements LPStrategy {
    @Override
    public BigDecimal[] solve(LpSolver lpSolver) {
        ExpressionsBasedModel model = lpSolver.getModel();
        int validCount = lpSolver.getValidCount();

//        System.out.println(model.getExpressions());

//        Optimisation.Result result =  model.minimise();
        SolverORTools tools = SolverORTools.INTEGRATION.build(model);

        Optimisation.Result result = tools.solve(null);
        if (result != null) {
            boolean validate = model.validate(result);
            // result.getState() == Optimisation.State.OPTIMAL ||
            if ((validate)) {
                result.getSolution(NumberContext.ofScale(0));

//            Optimisation.Result solution = result.getSolution(NumberContext.ofScale(2));
                Optimisation.Result solution = result.getSolution(NumberContext.ofScale(0));

                BigDecimal[] sols = new BigDecimal[validCount];

//            System.out.println("Length: " + sol.length);

                for (int i = 0; i < validCount; i++) {
//                System.out.println(solution.get(i).toString());
                    sols[i] = solution.get(i);
                }

                return sols;
            }
        }

        return null;
    }

    @Override
    public boolean preValidation(LpSolver lpSolver) {
        ExpressionsBasedModel model = lpSolver.getBaseModel();
        if (model.getExpressions().size() == 0) {
            return true;
        }
        int validCount = lpSolver.getValidCount();

//        System.out.println(model.getExpressions());

//        Optimisation.Result result =  model.minimise();
        SolverORTools tools = SolverORTools.INTEGRATION.build(model);

        Optimisation.Result result = tools.solve(null);
        if (result != null) {
            boolean validate = model.validate(result);
            // result.getState() == Optimisation.State.OPTIMAL ||
            if ((validate)) {
                result.getSolution(NumberContext.ofScale(0));
                return true;
            }
        }


        return false;
    }
}
